using SharpDX;
using System;
using System.Diagnostics;

namespace Engine.Graphics
{
    public class FpsCounter : IRenderableObject
    {
        #region Private Fields

        private double averageFPS = 0.0f;

        private Color4 colorLightGreen = new Color4()
        {
            Alpha = 1.0f,
            Red = 0.50f,
            Green = 1.0f,
            Blue = 0.5f
        };

        private Color4 colorOrange = new Color4()
        {
            Alpha = 1.0f,
            Red = 1.0f,
            Green = 0.5f,
            Blue = 0.0f
        };

        private Color4 colorRed = new Color4()
        {
            Alpha = 1.0f,
            Red = 1.0f,
            Green = 0.0f,
            Blue = 0.0f
        };

        private float elapsedMillisecondsLastCyle = 0;
        private long lastTotalMilliseconds = 0;
        private long lastUpdateMilliseconds = 0;
        private int numberOfCyles = 0;

        // milliseconds
        private Stopwatch sw = new Stopwatch();

        private Color4 textColor;
        private RenderText textOnScreen;
        private double updateInterval = 500;

        #endregion Private Fields

        #region Internal Constructors

        internal FpsCounter(Engine engine)
        {
            sw.Start();
            textOnScreen = new RenderText(engine.Grafic);
        }

        #endregion Internal Constructors

        #region Public Properties

        public float AverageFPS
        {
            get
            {
                return (float)this.averageFPS;
            }
        }

        public float ElapsedMillisecondsLastCyle
        {
            get { return this.elapsedMillisecondsLastCyle; }
            set { this.elapsedMillisecondsLastCyle = value; }
        }

        #endregion Public Properties

        #region Public Methods

        public void Dispose()
        {
            this.textOnScreen.Dispose();
        }

        public void Render(int renderStep)
        {
            this.textOnScreen.Render(renderStep);
        }

        #endregion Public Methods

        #region Internal Methods

        internal void Update()
        {
            this.numberOfCyles++;
            if (Environment.TickCount - this.lastUpdateMilliseconds > this.updateInterval)
            {
                this.averageFPS = (double)this.numberOfCyles / ((double)(Environment.TickCount - this.lastUpdateMilliseconds) / 1000.0d);
                this.lastUpdateMilliseconds = Environment.TickCount;
                this.numberOfCyles = 0;
            }
            this.elapsedMillisecondsLastCyle = (float)(Environment.TickCount - this.lastTotalMilliseconds);// / 1000.0f;
            this.lastTotalMilliseconds = Environment.TickCount;

            CalculateTextColor();

            this.textOnScreen.SetTextOnScreen(string.Format("{0:0.0} FPS ({1:0 ms)}", this.AverageFPS, this.elapsedMillisecondsLastCyle), 10, 100, this.textColor);
            this.elapsedMillisecondsLastCyle /= 1000.0f;
        }

        #endregion Internal Methods

        #region Private Methods

        private void CalculateTextColor()
        {
            // Set the Color
            if (this.AverageFPS > 25)
            {
                this.textColor = this.colorLightGreen;
            }
            else if (this.AverageFPS > 15)
            {
                this.textColor = this.colorOrange;
            }
            else
            {
                this.textColor = this.colorRed;
            }
        }

        #endregion Private Methods
    }
}